package com.javaweb.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.javaweb.entity.Result;
import com.javaweb.utils.JwtUtil;
import com.javaweb.utils.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.Map;

@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //目标资源方法运行前执行 返回true则放行 否则不放行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.获取请求url
        String url = request.getRequestURL().toString();
        log.info("请求的url：{}", url);

        //2.在config.WebConfig中设置需要拦截和放行的请求url

        //3.获取请求头中的令牌
        String token = request.getHeader("Authorization");


        //4.判断令牌是否存在 如果不存在 返回错误结果(未登录)
        if (!StringUtils.hasLength(token)){
            log.info("请求头token为空，返回未登录的信息");
            Result error = Result.error("NOT_LOGIN");
            //手动转换对象 JSON ----> 阿里巴巴fastJSON
            String errorStr = JSONObject.toJSONString(error);
            response.setStatus(401);
            response.getWriter().write(errorStr);
            return false;
        }


        //5.解析token 如果解析失败 返回错误结果(未登录)
        try{
            //从redis中获取相同的token
            ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
            String redisToken = operations.get(token);
            if (redisToken == null){
                //token已失效
                throw new RuntimeException();
            }

            Map<String, Object> claims = JwtUtil.parseToken(token);

            //把业务数据存储到ThreadLocal中
            ThreadLocalUtil.set(claims);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("解析令牌失败，返回未登录错误信息");
            Result error = Result.error("TOKEN_NOT_VALID");
            //手动转换对象 JSON ----> 阿里巴巴fastJSON
            String errorStr = JSONObject.toJSONString(error);
            response.setStatus(401);
            response.getWriter().write(errorStr);
            return false;
        }

        //6.放行
        log.info("令牌合法，允许访问");
        return true;
    }

    //视图渲染完毕后运行 最后运行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //清空ThreadLocal中的数据
        ThreadLocalUtil.remove();
    }
}
